package com.fatri.lessionsimple.camera

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import android.os.Bundle
import android.os.Handler
import android.view.Surface
import androidx.appcompat.app.AppCompatActivity
import com.fatri.lessionsimple.R
import com.fatri.lessionsimple.opengl.OpenGLTools
import kotlinx.android.synthetic.main.act_camera.*
import java.nio.FloatBuffer
import java.util.*
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10


class CameraAct : AppCompatActivity(), SurfaceTexture.OnFrameAvailableListener {
    lateinit var cameraDevice: CameraDevice   //Camera2
    lateinit var cameraCaptureSession: CameraCaptureSession
    lateinit var handler: Handler

    lateinit var myRender: MyRender
    lateinit var mSurfaceTexture: SurfaceTexture
    private var camera_status = 1  //1前置  0 后置
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.act_camera)
        handler = Handler()
        initView()
    }

    private fun initView() {
        myRender = MyRender()

        mCameraGlsurfaceView.setEGLContextClientVersion(2)
        mCameraGlsurfaceView.setRenderer(myRender)
        mCameraGlsurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY


        btn_switch_cam.setOnClickListener {
//            camera_status = camera_status xor 1


        }

    }

    fun openCamera1() {
        //            if (camera != null) {
//                camera.stopPreview()
//                camera.release()
//            }
//            myRender.mBool = true
//            camera = Camera.open(camera_status)
//            try {
//                camera.setPreviewTexture(mSurfaceTexture)
//            } catch (e: IOException) {
//                e.printStackTrace()
//            }
//            camera.startPreview()
    }

    @SuppressLint("MissingPermission")
    fun openCamera2() {
        val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        cameraManager.openCamera(camera_status.toString(), object : CameraDevice.StateCallback() {
            override fun onOpened(camera: CameraDevice) {
                cameraDevice=camera
            }

            override fun onDisconnected(camera: CameraDevice) {

            }

            override fun onError(camera: CameraDevice, error: Int) {

            }
        }, handler)
    }

//    fun startPreview() {
//        //设置SurfaceTexture的默认尺寸
//        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight())
//        //根据mSurfaceTexture创建Surface
//        val surface = Surface(mSurfaceTexture)
//        try {
//            //创建preview捕获请求
//            mCaptureRequestBuilder =
//                mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
//            //将此请求输出目标设为我们创建的Surface对象，这个Surface对象也必须添加给createCaptureSession才行
//            mCaptureRequestBuilder.addTarget(surface)
//            //创建捕获会话，第一个参数是捕获数据的输出Surface列表，第二个参数是CameraCaptureSession的状态回调接口，当它创建好后会回调onConfigured方法，第三个参数用来确定Callback在哪个线程执行，为null的话就在当前线程执行
//            mCameraDevice.createCaptureSession(
//                Arrays.asList(surface),
//                object : CameraCaptureSession.StateCallback() {
//                    override fun onConfigured(session: CameraCaptureSession) {
//                        try {
//                            //创建捕获请求
//                            mCaptureRequest = mCaptureRequestBuilder.build()
//                            mCameraCaptureSession = session
//                            //设置重复捕获数据的请求，之后surface绑定的SurfaceTexture中就会一直有数据到达，然后就会回调SurfaceTexture.OnFrameAvailableListener接口
//                            mCameraCaptureSession.setRepeatingRequest(
//                                mCaptureRequest,
//                                null,
//                                mCameraHandler
//                            )
//                        } catch (e: CameraAccessException) {
//                            e.printStackTrace()
//                        }
//                    }
//
//                    override fun onConfigureFailed(session: CameraCaptureSession) {}
//                },
//                mCameraHandler
//            )
//        } catch (e: CameraAccessException) {
//            e.printStackTrace()
//        }
//    }

    inner class MyRender : GLSurfaceView.Renderer {


        lateinit var mPosBuffer: FloatBuffer
        lateinit var mTexBuffer: FloatBuffer
        private val mPosCoordinate = floatArrayOf(
            -1f, -1f,
            -1f, 1f,
            1f, -1f,
            1f, 1f
        )

        private val mTexCoordinateBackRight =
            floatArrayOf(1f, 1f, 0f, 1f, 1f, 0f, 0f, 0f) //顺时针转90并沿Y轴翻转  后摄像头正确，前摄像头上下颠倒
        private val mTexCoordinateForntRight =
            floatArrayOf(0f, 1f, 1f, 1f, 0f, 0f, 1f, 0f) //顺时针旋转90  后摄像头上下颠倒了，前摄像头正确


        var mProgram: Int = -1
        var mBool = false

        private var uPosHandle = 0
        private var aTexHandle = 0
        private var mMVPMatrixHandle = 0
        private val mProjectMatrix = FloatArray(16)
        private val mCameraMatrix = FloatArray(16)
        private val mMVPMatrix = FloatArray(16)
        private val mTempMatrix = FloatArray(16)

        init {
            Matrix.setIdentityM(mProjectMatrix, 0)  //初始化4*4矩阵
            Matrix.setIdentityM(mCameraMatrix, 0)  //初始化4*4矩阵
            Matrix.setIdentityM(mMVPMatrix, 0)  //初始化4*4矩阵
            Matrix.setIdentityM(mTempMatrix, 0)  //初始化4*4矩阵

        }

        @SuppressLint("MissingPermission")
        override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
            GLES20.glClearColor(0f, 0f, 0f, 0f)
            mSurfaceTexture = SurfaceTexture(OpenGLTools.createOESTextureObject())
            createProgram()
            activeProgram()

//            camera = Camera.open(camera_status)
//            try {
//                camera.setPreviewTexture(mSurfaceTexture)
//                camera.startPreview()
//            } catch (e: Exception) {
//
//            }

            val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
            cameraManager.openCamera(
                camera_status.toString(),
                object : CameraDevice.StateCallback() {
                    override fun onOpened(camera: CameraDevice) {
                        //相机打开的回调
                        val previewSurface = Surface(mSurfaceTexture)
                        this@CameraAct.cameraDevice = camera
                        camera.createCaptureSession(mutableListOf(previewSurface), object :
                            CameraCaptureSession.StateCallback() {
                            override fun onConfigureFailed(session: CameraCaptureSession) {


                            }

                            override fun onConfigured(session: CameraCaptureSession) {
                                cameraCaptureSession = session

                                try {
                                    val builder: CaptureRequest.Builder
                                    builder =
                                        camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
                                    builder.addTarget(previewSurface)
                                    cameraCaptureSession.setRepeatingRequest(
                                        builder.build(),
                                        null,
                                        null
                                    )

                                } catch (e1: CameraAccessException) {
                                    // TODO 自动生成的 catch 块
                                    e1.printStackTrace()
                                }
                            }

                        }, null)
                    }

                    override fun onDisconnected(camera: CameraDevice) {

                    }

                    override fun onError(camera: CameraDevice, error: Int) {

                    }
                },
                handler
            )


        }


        override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
            GLES20.glViewport(0, 0, width, height)

            Matrix.scaleM(mMVPMatrix, 0, 1f, -1f, 1f)
            val ratio = width.toFloat() / height
            Matrix.orthoM(      //正交投影，物体呈现出来的大小不会随着其距离视点的远近而发生变化
                mProjectMatrix,
                0,
                -1f,
                1f,
                -ratio,
                ratio,
                1f,
                7f
            ) // 3和7代表远近视点与眼睛的距离，非坐标点

            Matrix.setLookAtM(  //设置相机位置
                mCameraMatrix,
                0,   //变换矩阵的起始位置（偏移量）
                0f,    //相机位置
                0f,
                3f,
                0f,  //观测点位置
                0f,
                0f,
                0f,     //up向量在xyz上的分量
                1.0f,
                0.0f
            ) // 3代表眼睛的坐标点

            Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mCameraMatrix, 0)

        }

        override fun onDrawFrame(gl: GL10?) {
            if (mBool) {
                activeProgram()
                mBool = false
            }

            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
            mSurfaceTexture.updateTexImage()
            GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0)
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, mPosCoordinate.size / 2)
        }

        /**
         * 创建程序
         */
        private fun createProgram() {
            mProgram = GLES20.glCreateProgram()

            val vertextShader = OpenGLTools.loadShader(
                GLES20.GL_VERTEX_SHADER,
                OpenGLTools.readShaderCode(this@CameraAct, "vertex_texture.glsl")
            )
            val textureShader =
                OpenGLTools.loadShader(
                    GLES20.GL_FRAGMENT_SHADER,
                    OpenGLTools.readShaderCode(this@CameraAct, "fragment_texture.glsl")
                )

            GLES20.glAttachShader(mProgram, vertextShader)
            GLES20.glAttachShader(mProgram, textureShader)

            GLES20.glLinkProgram(mProgram)

            //释放
            GLES20.glDeleteShader(vertextShader)
            GLES20.glDeleteShader(textureShader)
        }

        /**
         * 激活程序
         */
        private fun activeProgram() {
            GLES20.glUseProgram(mProgram)

            mSurfaceTexture.setOnFrameAvailableListener(this@CameraAct)

            //获取顶点着色器的位置句柄，字符串映射
            uPosHandle = GLES20.glGetAttribLocation(mProgram, "position")
            aTexHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate")
            mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "textureTransform");

            mPosBuffer = OpenGLTools.convertToFloatBuffer(mPosCoordinate)
            if (camera_status == 1) mTexBuffer =
                OpenGLTools.convertToFloatBuffer(mTexCoordinateForntRight)
            else mTexBuffer = OpenGLTools.convertToFloatBuffer(mTexCoordinateBackRight)


            //设置着色器参数
            GLES20.glVertexAttribPointer(uPosHandle, 2, GLES20.GL_FLOAT, false, 0, mPosBuffer)
            GLES20.glVertexAttribPointer(aTexHandle, 2, GLES20.GL_FLOAT, false, 0, mTexBuffer)

            //启用顶点位置的句柄
            GLES20.glEnableVertexAttribArray(uPosHandle)
            GLES20.glEnableVertexAttribArray(aTexHandle)
        }
    }

    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
        //SurfaceTexture画面回调
        //当SurfaceTexture接收到一帧数据时，请求OpenGL ES进行渲染
        mCameraGlsurfaceView.requestRender()
    }


}